const { isDigit, isKeywordChar } = require('./utils')

class Code {
    constructor(content) {
        this.content = content
        this.index = 0
    }

    // 判断是否读到 content 的末尾
    hasChar() {
        return this.index < this.content.length
    }
    // 读取当前下标的字符, 且下标 +1
    readChar() {
        if (this.hasChar()) {
            let i = this.index
            this.index += 1
            return this.content[i]
        } else {
            return null
        }
    }
    // 获取当前下标的字符，下标不变
    peekChar() {
        if (this.hasChar()) {
            return this.content[this.index]
        } else {
            return null
        }
    }
    readNumber() {
        let result = ''
        while (this.hasChar()) {
            let c = this.peekChar()
            if (isDigit(c)) {
                result += this.readChar()
            } else {
                break
            }
        }
        return Number(result)
    }
    readString() {
        const escapeStringMap = {
            "'": '\'',
            '"': '\"',
            '\\': '\\',
            'n': '\n',
            'r': '\r',
            'v': '\v',
            't': '\t',
            'b': '\b',
            'f': '\f',
            '\/': '/'
        }
        // 吃掉第一个引号
        this.readChar()
        let result = ''
        while (this.hasChar()) {
            let c = this.peekChar()
            if (c === '"') {
                // 吃掉第二个引号
                this.readChar()
                break
            } else if (c === '\\') {
                // 处理转义字符
                // 先把 \ 吃掉
                // 再获取后一位的字符作 key ，从转义字符表中取对应的转义符
                this.readChar()
                c = this.readChar()
                result += escapeStringMap[c]
            } else {
                result += this.readChar()
            }
        }
        return result
    }
    readKeyword() {
        let keyword = ''
        let keywords = {
            'null': null,
            'false': false,
            'true': true,
        }
        while (this.hasChar()) {
            let c = this.peekChar()
            if (isKeywordChar(c)) {
                keyword += this.readChar()
            } else {
                break
            }
        }
        if (keywords.hasOwnProperty(keyword)) {
            keyword = keywords[keyword]
        } else {
            throw new SyntaxError(`Unexpected token '${keyword}'`)
        }
        return keyword
    }
}

module.exports = Code
